package com.scut.campus.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.scut.campus.context.BaseContext;
import com.scut.campus.dto.PageDTO;
import com.scut.campus.dto.PostDto;
import com.scut.campus.entity.Post;
import com.scut.campus.infra.es.doc.PostDoc;
import com.scut.campus.infra.redis.RedisFixedSizeQueue;
import com.scut.campus.query.PostQuery;
import com.scut.campus.query.base.PageQuery;
import com.scut.campus.response.Result;
import com.scut.campus.service.LikeService;
import com.scut.campus.service.PostService;
import com.scut.campus.vo.PostVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@Tag(name = "帖子功能")
@RequestMapping("/post")
@Slf4j
public class PostController {

    @Autowired
    private PostService postService;

    @Autowired
    private LikeService likeService;

    @Autowired
    private RedisFixedSizeQueue redisFixedSizeQueue;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @Resource
    @Qualifier("transactionTemplate")
    TransactionTemplate transactionTemplate;

    @Resource
    @Qualifier("asyncTaskExecutor")
    private ThreadPoolTaskExecutor asyncTaskExecutor;

    private final static String POST_PREFIX = "post_prefix";

    @PostMapping("/insert")
    @Operation(summary = "发布帖子")
    public Result Post(@RequestBody PostDto postDto) throws IOException {
        Post post = new Post();
        BeanUtils.copyProperties(postDto, post);
        post.setUserId(BaseContext.getCurrentId());
        postService.save(post);

        //TODO 索引至es
        //更新redis缓存
        return Result.success();
    }


    @DeleteMapping("/del/{postId}")
    @Operation(summary = "删除帖子")
    public Result DeletePost(@PathVariable("postId") String postId) {
        LambdaQueryWrapper<Post> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(Post::getPostId, postId)
                .eq(Post::getUserId, BaseContext.getCurrentId());
        postService.remove(lambdaQueryWrapper);

        return Result.success();
    }

    @PostMapping("/update")
    @Operation(summary = "更新帖子")
    public Result UpdatePost(@RequestBody Post post) {
        //ensure user can only modify their own post
        post.setUserId(BaseContext.getCurrentId());

        postService.updateById(post);
        return Result.success();
    }

    @PostMapping("/query")
    @Operation(summary = "查询主页展示帖子")
    public Result<List<PostVo>> ListPost(@RequestBody PostQuery postQuery) {
        postQuery.setSortBy("update_timestamp");
        if (Strings.isBlank(postQuery.getTypeId())) {
            postQuery.setTypeId(null);
        }

        if (Strings.isBlank(postQuery.getStr()) && Strings.isBlank(postQuery.getTypeId())) {
            List<PostVo> postVoList = redisFixedSizeQueue.getAllFromQueue(POST_PREFIX)
                    .stream()
                    .map(obj -> objectMapper.convertValue(obj, PostVo.class))
                    .collect(Collectors.toList());


            if (postVoList.size() >= 10) {
                return Result.success(postVoList);
            }

        }


/*        for(PostVo postVo : postVos){
            redisFixedSizeQueue.push(POST_PREFIX, postVo);
        }*/
        //4、插入redis
        //stringRedisTemplate.opsForValue().set(key,objectMapper.writeValueAsString(postVos));

        //TODO 更新逻辑
        List<PostVo> postVos = postService.queryMainPost(postQuery);


        return Result.success(postVos);
    }

    @PostMapping("/like/{postId}")
    @Operation(summary = "点赞帖子")
    public Result likePost(@PathVariable String postId) {
        //TODO notify

        transactionTemplate.executeWithoutResult(transactionStatus -> {
            likeService.insertPostLike(postId);
            postService.likePost(postId);
        });

        return Result.success();
    }

    @PostMapping("/dislike/{postId}")
    @Operation(summary = "取消点赞")
    public Result dislikePost(@PathVariable("postId") String postId) {

        transactionTemplate.executeWithoutResult(
                transactionStatus -> {
                    likeService.deleteByPostId(postId, true);
                    postService.dislikePost(postId);
                }
        );

        return Result.success();
    }

    @GetMapping("/queryMyPost")
    @Operation(summary = "分页查询我的帖子")
    public Result<PageDTO<Post>> queryMyPost(PageQuery pageQuery) {
        PageDTO<Post> pageResult = postService.queryMyPost(pageQuery);
        return Result.success(pageResult);
    }

    @GetMapping("/getSinglePost/{postId}")
    @Operation(summary = "获取单个帖子详情")
    public Result<Post> getSinglePost(@PathVariable String postId) throws IOException {
        Post post = postService.getSinglePost(postId);

        asyncTaskExecutor.execute(() -> postService.visitPost(postId));

        //Long total=commentService.commentCount(postId);


        PostDoc postDoc = BeanUtil.copyProperties(post, PostDoc.class);
        String doc = JSONUtil.toJsonStr(postDoc);

/*        IndexRequest request = new IndexRequest("posts").id(postDoc.getPostId().toString());
        request.source(doc, XContentType.JSON);

        RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://8.138.180.23:9200")
        ));
        client.index(request, RequestOptions.DEFAULT);*/

        return Result.success(post);
    }

}
